1 /* 2 * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.awt.image; 27 import java.awt.image.Raster; 28 import java.awt.image.WritableRaster; 29 import java.awt.image.RasterFormatException; 30 import java.awt.image.SampleModel; 31 import java.awt.image.BandedSampleModel; 32 import java.awt.image.DataBuffer; 33 import java.awt.image.DataBufferUShort; 34 import java.awt.Rectangle; 35 import java.awt.Point; 36 37 /** 38 * This class defines a Raster with pixels consisting of multiple 16-bit 39 * samples stored in separate arrays for each band. Operations on 40 * sets of pixels are performed on a given band of each pixel 41 * in the set before moving on to the next band. The arrays used 42 * for storage may be distinct or shared between some or all of 43 * the bands. 44 * There is only one pixel stride and one scanline stride for all 45 * bands. This type of Raster can be used with a 46 * ComponentColorModel. This class requires a BandedSampleModel. 47 * 48 */ 49 public class ShortBandedRaster extends SunWritableRaster { 50 51 /** Data offsets for each band of image data. */ 52 int[] dataOffsets; 53 54 /** Scanline stride of the image data contained in this Raster. */ 55 int scanlineStride; 56 57 /** The image data array. */ 58 short[][] data; 59 60 /** A cached copy of minX + width for use in bounds checks. */ 61 private int maxX; 62 63 /** A cached copy of minY + height for use in bounds checks. */ 64 private int maxY; 65 66 /** 67 * Constructs a ShortBandedRaster with the given SampleModel. 68 * The Raster's upper left corner is origin and it is the same 69 * size as the SampleModel. A DataBuffer large enough to describe the 70 * Raster is automatically created. SampleModel must be of type 71 * BandedSampleModel. 72 * @param sampleModel The SampleModel that specifies the layout. 73 * @param origin The Point that specified the origin. 74 */ 75 public ShortBandedRaster(SampleModel sampleModel, 76 Point origin) { 77 this(sampleModel, 78 sampleModel.createDataBuffer(), 79 new Rectangle(origin.x, 80 origin.y, 81 sampleModel.getWidth(), 82 sampleModel.getHeight()), 83 origin, 84 null); 85 } 86 87 /** 88 * Constructs a ShortBandedRaster with the given SampleModel 89 * and DataBuffer. The Raster's upper left corner is origin and 90 * it is the same size as the SampleModel. The DataBuffer is not 91 * initialized and must be a DataBufferUShort compatible with SampleModel. 92 * SampleModel must be of type BandedSampleModel. 93 * @param sampleModel The SampleModel that specifies the layout. 94 * @param dataBuffer The DataBufferUShort that contains the image data. 95 * @param origin The Point that specifies the origin. 96 */ 97 public ShortBandedRaster(SampleModel sampleModel, 98 DataBuffer dataBuffer, 99 Point origin) { 100 this(sampleModel, dataBuffer, 101 new Rectangle(origin.x, origin.y, 102 sampleModel.getWidth(), 103 sampleModel.getHeight()), 104 origin, null); 105 } 106 107 /** 108 * Constructs a ShortBandedRaster with the given SampleModel, 109 * DataBuffer, and parent. DataBuffer must be a DataBufferUShort and 110 * SampleModel must be of type BandedSampleModel. 111 * When translated into the base Raster's 112 * coordinate system, aRegion must be contained by the base Raster. 113 * Origin is the coordinate in the new Raster's coordinate system of 114 * the origin of the base Raster. (The base Raster is the Raster's 115 * ancestor which has no parent.) 116 * 117 * Note that this constructor should generally be called by other 118 * constructors or create methods, it should not be used directly. 119 * @param sampleModel The SampleModel that specifies the layout. 120 * @param dataBuffer The DataBufferUShort that contains the image data. 121 * @param aRegion The Rectangle that specifies the image area. 122 * @param origin The Point that specifies the origin. 123 * @param parent The parent (if any) of this raster. 124 */ 125 public ShortBandedRaster(SampleModel sampleModel, 126 DataBuffer dataBuffer, 127 Rectangle aRegion, 128 Point origin, 129 ShortBandedRaster parent) { 130 131 super(sampleModel, dataBuffer, aRegion, origin, parent); 132 this.maxX = minX + width; 133 this.maxY = minY + height; 134 if (!(dataBuffer instanceof DataBufferUShort)) { 135 throw new RasterFormatException("ShortBandedRaster must have " + 136 "ushort DataBuffers"); 137 } 138 DataBufferUShort dbus = (DataBufferUShort)dataBuffer; 139 140 if (sampleModel instanceof BandedSampleModel) { 141 BandedSampleModel bsm = (BandedSampleModel)sampleModel; 142 this.scanlineStride = bsm.getScanlineStride(); 143 int bankIndices[] = bsm.getBankIndices(); 144 int bandOffsets[] = bsm.getBandOffsets(); 145 int dOffsets[] = dbus.getOffsets(); 146 dataOffsets = new int[bankIndices.length]; 147 data = new short[bankIndices.length][]; 148 int xOffset = aRegion.x - origin.x; 149 int yOffset = aRegion.y - origin.y; 150 for (int i = 0; i < bankIndices.length; i++) { 151 data[i] = stealData(dbus, bankIndices[i]); 152 dataOffsets[i] = dOffsets[bankIndices[i]] + 153 xOffset + yOffset*scanlineStride + bandOffsets[i]; 154 } 155 } else { 156 throw new RasterFormatException("ShortBandedRasters must have "+ 157 "BandedSampleModels"); 158 } 159 verify(false); 160 } 161 162 /** 163 * Returns a copy of the data offsets array. For each band the data offset 164 * is the index into the band's data array, of the first sample of the 165 * band. 166 */ 167 public int[] getDataOffsets() { 168 return (int[]) dataOffsets.clone(); 169 } 170 171 /** 172 * Returns the data offset for the specified band. The data offset 173 * is the index into the band's data array 174 * in which the first sample of the first scanline is stored. 175 * @param The band whose offset is returned. 176 */ 177 public int getDataOffset(int band) { 178 return dataOffsets[band]; 179 } 180 181 /** 182 * Returns the scanline stride -- the number of data array elements between 183 * a given sample and the sample in the same column 184 * of the next row in the same band. 185 */ 186 public int getScanlineStride() { 187 return scanlineStride; 188 } 189 190 /** 191 * Returns the pixel stride, which is always equal to one for 192 * a Raster with a BandedSampleModel. 193 */ 194 public int getPixelStride() { 195 return 1; 196 } 197 198 /** 199 * Returns a reference to the entire data array. 200 */ 201 public short[][] getDataStorage() { 202 return data; 203 } 204 205 /** 206 * Returns a reference to the specific band data array. 207 */ 208 public short[] getDataStorage(int band) { 209 return data[band]; 210 } 211 212 /** 213 * Returns the data elements for all bands at the specified 214 * location. 215 * An ArrayIndexOutOfBounds exception will be thrown at runtime 216 * if the pixel coordinate is out of bounds. 217 * A ClassCastException will be thrown if the input object is non null 218 * and references anything other than an array of transferType. 219 * @param x The X coordinate of the pixel location. 220 * @param y The Y coordinate of the pixel location. 221 * @param outData An object reference to an array of type defined by 222 * getTransferType() and length getNumDataElements(). 223 * If null an array of appropriate type and size will be 224 * allocated. 225 * @return An object reference to an array of type defined by 226 * getTransferType() with the request pixel data. 227 */ 228 public Object getDataElements(int x, int y, Object obj) { 229 if ((x < this.minX) || (y < this.minY) || 230 (x >= this.maxX) || (y >= this.maxY)) { 231 throw new ArrayIndexOutOfBoundsException 232 ("Coordinate out of bounds!"); 233 } 234 short outData[]; 235 if (obj == null) { 236 outData = new short[numDataElements]; 237 } else { 238 outData = (short[])obj; 239 } 240 241 int off = (y-minY)*scanlineStride + (x-minX); 242 243 for (int band = 0; band < numDataElements; band++) { 244 outData[band] = data[band][dataOffsets[band] + off]; 245 } 246 247 return outData; 248 } 249 250 /** 251 * Returns an array of data elements from the specified rectangular 252 * region. 253 * An ArrayIndexOutOfBounds exception will be thrown at runtime 254 * if the pixel coordinates are out of bounds. 255 * <pre> 256 * short[] bandData = (short[])Raster.getDataElements(x, y, w, h, null); 257 * int numDataElements = Raster.getnumDataElements(); 258 * short[] pixel = new short[numDataElements]; 259 * // To find a data element at location (x2, y2) 260 * System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements, 261 * pixel, 0, numDataElements); 262 * </pre> 263 * @param x The X coordinate of the upper left pixel location. 264 * @param y The Y coordinate of the upper left pixel location. 265 * @param width Width of the pixel rectangle. 266 * @param height Height of the pixel rectangle. 267 * @param outData An object reference to an array of type defined by 268 * getTransferType() and length w*h*getNumDataElements(). 269 * If null an array of appropriate type and size will be 270 * allocated. 271 * @return An object reference to an array of type defined by 272 * getTransferType() with the request pixel data. 273 */ 274 public Object getDataElements(int x, int y, int w, int h, Object obj) { 275 if ((x < this.minX) || (y < this.minY) || 276 (x + w > this.maxX) || (y + h > this.maxY)) { 277 throw new ArrayIndexOutOfBoundsException 278 ("Coordinate out of bounds!"); 279 } 280 short outData[]; 281 if (obj == null) { 282 outData = new short[numDataElements*w*h]; 283 } else { 284 outData = (short[])obj; 285 } 286 int yoff = (y-minY)*scanlineStride + (x-minX); 287 288 for (int c = 0; c < numDataElements; c++) { 289 int off = c; 290 short[] bank = data[c]; 291 int dataOffset = dataOffsets[c]; 292 293 int yoff2 = yoff; 294 for (int ystart=0; ystart < h; ystart++, yoff2 += scanlineStride) { 295 int xoff = dataOffset + yoff2; 296 for (int xstart=0; xstart < w; xstart++) { 297 outData[off] = bank[xoff++]; 298 off += numDataElements; 299 } 300 } 301 } 302 303 return outData; 304 } 305 306 /** 307 * Returns a short array of data elements from the specified rectangular 308 * region for the specified band. 309 * An ArrayIndexOutOfBounds exception will be thrown at runtime 310 * if the pixel coordinates are out of bounds. 311 * <pre> 312 * short[] bandData = Raster.getShortData(x, y, w, h, null); 313 * // To find the data element at location (x2, y2) 314 * short bandElement = bandData[((y2-y)*w + (x2-x))]; 315 * </pre> 316 * @param x The X coordinate of the upper left pixel location. 317 * @param y The Y coordinate of the upper left pixel location. 318 * @param width Width of the pixel rectangle. 319 * @param height Height of the pixel rectangle. 320 * @param band The band to return. 321 * @param outData If non-null, data elements for all bands 322 * at the specified location are returned in this array. 323 * @return Data array with data elements for all bands. 324 */ 325 public short[] getShortData(int x, int y, int w, int h, 326 int band, short[] outData) { 327 // Bounds check for 'band' will be performed automatically 328 if ((x < this.minX) || (y < this.minY) || 329 (x + w > this.maxX) || (y + h > this.maxY)) { 330 throw new ArrayIndexOutOfBoundsException 331 ("Coordinate out of bounds!"); 332 } 333 if (outData == null) { 334 outData = new short[scanlineStride*h]; 335 } 336 int yoff = (y-minY)*scanlineStride + (x-minX) + dataOffsets[band]; 337 338 if (scanlineStride == w) { 339 System.arraycopy(data[band], yoff, outData, 0, w*h); 340 } else { 341 int off = 0; 342 for (int ystart=0; ystart < h; ystart++, yoff += scanlineStride) { 343 System.arraycopy(data[band], yoff, outData, off, w); 344 off += w; 345 } 346 } 347 348 return outData; 349 } 350 351 /** 352 * Returns a short array of data elements from the specified rectangular 353 * region. 354 * An ArrayIndexOutOfBounds exception will be thrown at runtime 355 * if the pixel coordinates are out of bounds. 356 * <pre> 357 * short[] bandData = Raster.getShortData(x, y, w, h, null); 358 * int numDataElements = Raster.getnumDataElements(); 359 * short[] pixel = new short[numDataElements]; 360 * // To find a data element at location (x2, y2) 361 * System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements, 362 * pixel, 0, numDataElements); 363 * </pre> 364 * @param x The X coordinate of the upper left pixel location. 365 * @param y The Y coordinate of the upper left pixel location. 366 * @param width Width of the pixel rectangle. 367 * @param height Height of the pixel rectangle. 368 * @param outData If non-null, data elements for all bands 369 * at the specified location are returned in this array. 370 * @return Data array with data elements for all bands. 371 */ 372 public short[] getShortData(int x, int y, int w, int h, 373 short[] outData) { 374 if ((x < this.minX) || (y < this.minY) || 375 (x + w > this.maxX) || (y + h > this.maxY)) { 376 throw new ArrayIndexOutOfBoundsException 377 ("Coordinate out of bounds!"); 378 } 379 if (outData == null) { 380 outData = new short[numDataElements*scanlineStride*h]; 381 } 382 int yoff = (y-minY)*scanlineStride + (x-minX); 383 384 for (int c = 0; c < numDataElements; c++) { 385 int off = c; 386 short[] bank = data[c]; 387 int dataOffset = dataOffsets[c]; 388 389 int yoff2 = yoff; 390 for (int ystart=0; ystart < h; ystart++, yoff2 += scanlineStride) { 391 int xoff = dataOffset + yoff2; 392 for (int xstart=0; xstart < w; xstart++) { 393 outData[off] = bank[xoff++]; 394 off += numDataElements; 395 } 396 } 397 } 398 399 return outData; 400 } 401 402 /** 403 * Stores the data element for all bands at the specified location. 404 * An ArrayIndexOutOfBounds exception will be thrown at runtime 405 * if the pixel coordinate is out of bounds. 406 * A ClassCastException will be thrown if the input object is non null 407 * and references anything other than an array of transferType. 408 * @param x The X coordinate of the pixel location. 409 * @param y The Y coordinate of the pixel location. 410 * @param inData An object reference to an array of type defined by 411 * getTransferType() and length getNumDataElements() 412 * containing the pixel data to place at x,y. 413 */ 414 public void setDataElements(int x, int y, Object obj) { 415 if ((x < this.minX) || (y < this.minY) || 416 (x >= this.maxX) || (y >= this.maxY)) { 417 throw new ArrayIndexOutOfBoundsException 418 ("Coordinate out of bounds!"); 419 } 420 short inData[] = (short[])obj; 421 int off = (y-minY)*scanlineStride + (x-minX); 422 for (int i = 0; i < numDataElements; i++) { 423 data[i][dataOffsets[i] + off] = inData[i]; 424 } 425 426 markDirty(); 427 } 428 429 /** 430 * Stores the Raster data at the specified location. 431 * An ArrayIndexOutOfBounds exception will be thrown at runtime 432 * if the pixel coordinates are out of bounds. 433 * @param x The X coordinate of the pixel location. 434 * @param y The Y coordinate of the pixel location. 435 * @param inRaster Raster of data to place at x,y location. 436 */ 437 public void setDataElements(int x, int y, Raster inRaster) { 438 int dstOffX = x + inRaster.getMinX(); 439 int dstOffY = y + inRaster.getMinY(); 440 int width = inRaster.getWidth(); 441 int height = inRaster.getHeight(); 442 if ((dstOffX < this.minX) || (dstOffY < this.minY) || 443 (dstOffX + width > this.maxX) || (dstOffY + height > this.maxY)) { 444 throw new ArrayIndexOutOfBoundsException 445 ("Coordinate out of bounds!"); 446 } 447 448 setDataElements(dstOffX, dstOffY, width, height, inRaster); 449 } 450 451 /** 452 * Stores the Raster data at the specified location. 453 * @param dstX The absolute X coordinate of the destination pixel 454 * that will receive a copy of the upper-left pixel of the 455 * inRaster 456 * @param dstY The absolute Y coordinate of the destination pixel 457 * that will receive a copy of the upper-left pixel of the 458 * inRaster 459 * @param width The number of pixels to store horizontally 460 * @param height The number of pixels to store vertically 461 * @param inRaster Raster of data to place at x,y location. 462 */ 463 private void setDataElements(int dstX, int dstY, 464 int width, int height, 465 Raster inRaster) { 466 // Assume bounds checking has been performed previously 467 if (width <= 0 || height <= 0) { 468 return; 469 } 470 471 // Write inRaster (minX, minY) to (dstX, dstY) 472 473 int srcOffX = inRaster.getMinX(); 474 int srcOffY = inRaster.getMinY(); 475 Object tdata = null; 476 477 // // REMIND: Do something faster! 478 // if (inRaster instanceof ShortBandedRaster) { 479 // } 480 481 for (int startY=0; startY < height; startY++) { 482 // Grab one scanline at a time 483 tdata = inRaster.getDataElements(srcOffX, srcOffY+startY, 484 width, 1, tdata); 485 setDataElements(dstX, dstY + startY, width, 1, tdata); 486 } 487 } 488 489 /** 490 * Stores an array of data elements into the specified rectangular 491 * region. 492 * An ArrayIndexOutOfBounds exception will be thrown at runtime 493 * if the pixel coordinates are out of bounds. 494 * A ClassCastException will be thrown if the input object is non null 495 * and references anything other than an array of transferType. 496 * The data elements in the 497 * data array are assumed to be packed. That is, a data element 498 * for the nth band at location (x2, y2) would be found at: 499 * <pre> 500 * inData[((y2-y)*w + (x2-x))*numDataElements + n] 501 * </pre> 502 * @param x The X coordinate of the upper left pixel location. 503 * @param y The Y coordinate of the upper left pixel location. 504 * @param w Width of the pixel rectangle. 505 * @param h Height of the pixel rectangle. 506 * @param inData An object reference to an array of type defined by 507 * getTransferType() and length w*h*getNumDataElements() 508 * containing the pixel data to place between x,y and 509 * x+h, y+h. 510 */ 511 public void setDataElements(int x, int y, int w, int h, Object obj) { 512 if ((x < this.minX) || (y < this.minY) || 513 (x + w > this.maxX) || (y + h > this.maxY)) { 514 throw new ArrayIndexOutOfBoundsException 515 ("Coordinate out of bounds!"); 516 } 517 short inData[] = (short[])obj; 518 int yoff = (y-minY)*scanlineStride + (x-minX); 519 520 for (int c = 0; c < numDataElements; c++) { 521 int off = c; 522 short[] bank = data[c]; 523 int dataOffset = dataOffsets[c]; 524 525 int yoff2 = yoff; 526 for (int ystart=0; ystart < h; ystart++, yoff2 += scanlineStride) { 527 int xoff = dataOffset + yoff2; 528 for (int xstart=0; xstart < w; xstart++) { 529 bank[xoff++] = inData[off]; 530 off += numDataElements; 531 } 532 } 533 } 534 535 markDirty(); 536 } 537 538 /** 539 * Stores a short array of data elements into the specified 540 * rectangular region for the specified band. 541 * An ArrayIndexOutOfBounds exception will be thrown at runtime 542 * if the pixel coordinates are out of bounds. 543 * The data elements in the 544 * data array are assumed to be packed. That is, a data element 545 * at location (x2, y2) would be found at: 546 * <pre> 547 * inData[((y2-y)*w + (x2-x))] 548 * </pre> 549 * @param x The X coordinate of the upper left pixel location. 550 * @param y The Y coordinate of the upper left pixel location. 551 * @param w Width of the pixel rectangle. 552 * @param h Height of the pixel rectangle. 553 * @param band The band to set. 554 * @param inData The data elements to be stored. 555 */ 556 public void putShortData(int x, int y, int w, int h, 557 int band, short[] inData) { 558 // Bounds check for 'band' will be performed automatically 559 if ((x < this.minX) || (y < this.minY) || 560 (x + w > this.maxX) || (y + h > this.maxY)) { 561 throw new ArrayIndexOutOfBoundsException 562 ("Coordinate out of bounds!"); 563 } 564 int yoff = (y-minY)*scanlineStride + (x-minX) + dataOffsets[band]; 565 int xoff; 566 int off = 0; 567 int xstart; 568 int ystart; 569 570 if (scanlineStride == w) { 571 System.arraycopy(inData, 0, data[band], yoff, w*h); 572 } else { 573 for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) { 574 System.arraycopy(inData, off, data[band], yoff, w); 575 off += w; 576 } 577 } 578 579 markDirty(); 580 } 581 582 /** 583 * Stores a short integer array of data elements into the specified 584 * rectangular region. 585 * An ArrayIndexOutOfBounds exception will be thrown at runtime 586 * if the pixel coordinates are out of bounds. 587 * The data elements in the 588 * data array are assumed to be packed. That is, a data element 589 * for the nth band at location (x2, y2) would be found at: 590 * <pre> 591 * inData[((y2-y)*w + (x2-x))*numDataElements + n] 592 * </pre> 593 * @param x The X coordinate of the upper left pixel location. 594 * @param y The Y coordinate of the upper left pixel location. 595 * @param w Width of the pixel rectangle. 596 * @param h Height of the pixel rectangle. 597 * @param inData The data elements to be stored. 598 */ 599 public void putShortData(int x, int y, int w, int h, short[] inData) { 600 if ((x < this.minX) || (y < this.minY) || 601 (x + w > this.maxX) || (y + h > this.maxY)) { 602 throw new ArrayIndexOutOfBoundsException 603 ("Coordinate out of bounds!"); 604 } 605 int yoff = (y-minY)*scanlineStride + (x-minX); 606 607 for (int c = 0; c < numDataElements; c++) { 608 int off = c; 609 short[] bank = data[c]; 610 int dataOffset = dataOffsets[c]; 611 612 int yoff2 = yoff; 613 for (int ystart=0; ystart < h; ystart++, yoff2 += scanlineStride) { 614 int xoff = dataOffset + yoff2; 615 for (int xstart=0; xstart < w; xstart++) { 616 bank[xoff++] = inData[off]; 617 off += numDataElements; 618 } 619 } 620 } 621 622 markDirty(); 623 } 624 625 /** 626 * Creates a Writable subRaster given a region of the Raster. The x and y 627 * coordinates specify the horizontal and vertical offsets 628 * from the upper-left corner of this Raster to the upper-left corner 629 * of the subRaster. A subset of the bands of the parent Raster may 630 * be specified. If this is null, then all the bands are present in the 631 * subRaster. A translation to the subRaster may also be specified. 632 * Note that the subRaster will reference the same 633 * DataBuffers as the parent Raster, but using different offsets. 634 * @param x X offset. 635 * @param y Y offset. 636 * @param width Width (in pixels) of the subraster. 637 * @param height Height (in pixels) of the subraster. 638 * @param x0 Translated X origin of the subraster. 639 * @param y0 Translated Y origin of the subraster. 640 * @param bandList Array of band indices. 641 * @exception RasterFormatException 642 * if the specified bounding box is outside of the parent Raster. 643 */ 644 public WritableRaster createWritableChild(int x, int y, 645 int width, int height, 646 int x0, int y0, 647 int bandList[]) { 648 649 if (x < this.minX) { 650 throw new RasterFormatException("x lies outside raster"); 651 } 652 if (y < this.minY) { 653 throw new RasterFormatException("y lies outside raster"); 654 } 655 if ((x+width < x) || (x+width > this.minX + this.width)) { 656 throw new RasterFormatException("(x + width) is outside of Raster"); 657 } 658 if ((y+height < y) || (y+height > this.minY + this.height)) { 659 throw new RasterFormatException("(y + height) is outside of Raster"); 660 } 661 662 SampleModel sm; 663 664 if (bandList != null) 665 sm = sampleModel.createSubsetSampleModel(bandList); 666 else 667 sm = sampleModel; 668 669 int deltaX = x0 - x; 670 int deltaY = y0 - y; 671 672 return new ShortBandedRaster(sm, 673 dataBuffer, 674 new Rectangle(x0, y0, width, height), 675 new Point(sampleModelTranslateX+deltaX, 676 sampleModelTranslateY+deltaY), 677 this); 678 679 } 680 681 /** 682 * Creates a subraster given a region of the raster. The x and y 683 * coordinates specify the horizontal and vertical offsets 684 * from the upper-left corner of this raster to the upper-left corner 685 * of the subraster. A subset of the bands of the parent Raster may 686 * be specified. If this is null, then all the bands are present in the 687 * subRaster. A translation to the subRaster may also be specified. 688 * Note that the subraster will reference the same 689 * DataBuffers as the parent raster, but using different offsets. 690 * @param x X offset. 691 * @param y Y offset. 692 * @param width Width (in pixels) of the subraster. 693 * @param height Height (in pixels) of the subraster. 694 * @param x0 Translated X origin of the subraster. 695 * @param y0 Translated Y origin of the subraster. 696 * @param bandList Array of band indices. 697 * @exception RasterFormatException 698 * if the specified bounding box is outside of the parent raster. 699 */ 700 public Raster createChild (int x, int y, 701 int width, int height, 702 int x0, int y0, 703 int bandList[]) { 704 return createWritableChild(x, y, width, height, x0, y0, bandList); 705 } 706 707 /** 708 * Creates a Raster with the same layout but using a different 709 * width and height, and with new zeroed data arrays. 710 */ 711 public WritableRaster createCompatibleWritableRaster(int w, int h) { 712 if (w <= 0 || h <=0) { 713 throw new RasterFormatException("negative "+ 714 ((w <= 0) ? "width" : "height")); 715 } 716 717 SampleModel sm = sampleModel.createCompatibleSampleModel(w,h); 718 719 return new ShortBandedRaster(sm, new Point(0,0)); 720 } 721 722 /** 723 * Creates a Raster with the same layout and the same 724 * width and height, and with new zeroed data arrays. If 725 * the Raster is a subRaster, this will call 726 * createCompatibleRaster(width, height). 727 */ 728 public WritableRaster createCompatibleWritableRaster() { 729 return createCompatibleWritableRaster(width,height); 730 } 731 732 /** 733 * Verify that the layout parameters are consistent with 734 * the data. If strictCheck 735 * is false, this method will check for ArrayIndexOutOfBounds conditions. If 736 * strictCheck is true, this method will check for additional error 737 * conditions such as line wraparound (width of a line greater than 738 * the scanline stride). 739 * @return String Error string, if the layout is incompatible with 740 * the data. Otherwise returns null. 741 */ 742 private void verify (boolean strictCheck) { 743 // Make sure data for Raster is in a legal range 744 for (int i=0; i < dataOffsets.length; i++) { 745 if (dataOffsets[i] < 0) { 746 throw new RasterFormatException("Data offsets for band "+i+ 747 "("+dataOffsets[i]+ 748 ") must be >= 0"); 749 } 750 } 751 752 int maxSize = 0; 753 int size; 754 755 for (int i=0; i < numDataElements; i++) { 756 size = (height-1)*scanlineStride + (width-1) + dataOffsets[i]; 757 if (size > maxSize) { 758 maxSize = size; 759 } 760 } 761 for (int i=0; i < numDataElements; i++) { 762 if (data[i].length < maxSize) { 763 throw new RasterFormatException("Data array too small (should be "+ 764 maxSize+" )"); 765 } 766 } 767 } 768 769 public String toString() { 770 return new String ("ShortBandedRaster: width = "+width+" height = " 771 + height 772 +" #numBands " + numBands 773 +" #dataElements "+numDataElements); 774 775 } 776 777 }